贪心算法-----------------装箱问题

贪心算法中必须设定一个贪心准则-----来寻求每一步的最优解,但最后往往不是问题的整体最优解。

问题:假设有n个物品,其体积为V1,V2,V3,V4.......Vn,有若干个体积为V的箱子(理论物品的体积应该小于箱子的体积)

要求把所有物品全部装入箱子中,要求打开的箱子数最少。

分析:怎样合理化分配才能使得打开的箱子数最少呢?首先我们应该把所有的物品体积进行降序排序,先把体积最大的物品进行装箱

第二个物品从第一个箱子进行遍历看第一个箱子剩余的空间是否能容纳此物品,如果可以就装入,如果不可以就再开一个箱子,剩余

的物品依次类推。------------这也就是装箱问题的贪心准则。

声明物品信息的结构体-------物品编号,物品体积

声明物品节点和箱子节点的结构体---------相当于所有打开的箱子拉成了一条链表每个箱子上面的物品又会形成一条链表

#include<stdio.h>
#include<stdlib.h>
#define N 5
#define V 10
typedef struct
{
	int gno;//物品编号
	int gv;//物品体积
}ElemG;//物品信息
typedef struct node
{
	int gno;
	struct node *link;
}GoodsLink;//物品节点
typedef struct box
{
	int reminder;//剩余体积
	GoodsLink *hg;//物品节点的头指针
	struct box *next;
}BoxLink;//箱子节点
BoxLink *BinPacking()
{
ElemG *g;
int i,j;
BoxLink *p,*tail,*hbox=NULL;
GoodsLink *new1,*q;
g=(ElemG *)malloc(N *sizeof(ElemG));
//物品信息的初始化
for(i=0;i<N;i++)
{
	g[i].gno=i+1;
	printf("请输入第%d个物品的体积:",i+1);
	scanf("%d",&g[i].gv);
}
//按照体积从大到小降序排序
for(i=0;i<N;i++)
{
	int t;
	for(j=i+1;j<N;j++)
	{
		if(g[i].gv<g[j].gv )
		{	
			t=g[i].gno ;
			g[i].gno= g[j].gno ;
			g[j].gno= t;
			t=g[i].gv ;
			g[i].gv = g[j].gv ;
			g[j].gv = t;
		}
	}
} 
//遍历所有已排序的物品
for(i=0;i<N;i++)
{
//遍历箱子链
	for(p=hbox;p&&p->reminder<g[i].gv;p=p->next);
	if(!p)//开新箱子(1.第一个物品进入2.遍历箱子后没有一个箱子的剩余空间可以放下此物品)
	{
		//创建箱子节点
		p=(BoxLink *)malloc(sizeof(BoxLink));
		//初始化箱子
		p->reminder=V;
		p->next=NULL;
		p->hg=NULL;
		if(!hbox)//挂箱子
			hbox=tail=p;
		else
			tail=tail->next=p;
	}
	//创建物品节点
	new1=(GoodsLink *)malloc(sizeof(GoodsLink));
	new1->gno=g[i].gno;
	new1->link=NULL;
	if(!p->hg)//判断要挂的箱子上是不是NULL
		p->hg=new1;
	else
	{
		for(q=p->hg;q->link;q=q->link);//遍历箱子节点上的物体尾插
		q->link=new1;
	}
	p->reminder=p->reminder-g[i].gv;//每次放入一个物品都需要算出剩余空间
}
return hbox;
}
int main()
{
BoxLink *p,*hbox;
GoodsLink *q;
int cnt=0;
//输出
hbox=BinPacking();
for(p=hbox;p;p=p->next)
{
	printf("第%d个箱子:",++cnt);
	for(q=p->hg;q;q=q->link)
		printf("%3d",q->gno);
	printf("\n");
}
}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值